﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Xml.Linq;
using System.Threading;

namespace Html5.ManifestController
{
    public partial class Form1 : Form
    {
        private string currentDirectory;
        private string configFileFullPath;
        private const string configFileName = "ManifestController.config";
        private ManifestControllerModel listeningConfig;
        private Dictionary<string, DateTime> fileModifyTimeList;

        private Thread thread;

        public Form1()
        {
            InitializeComponent();
        }

        ~Form1()
        {
            if (thread != null & thread.ThreadState == ThreadState.Running)
            {
                thread.Abort();
            }
            thread = null;
        }

        /// <summary>
        /// 检查配置文件是否存在，如果不存在，则添加
        /// </summary>
        private void CheckConfigFile()
        {
            if (!File.Exists(configFileFullPath))
            {
                //不存在配置文件，添加
                ManifestControllerModel model = new ManifestControllerModel()
                {
                    Cache = "",
                    CacheDependence = "",
                    Fallback = "",
                    Network = "",
                    SyncCacheToCacheDependence = false,
                    UpdateMode = 0
                };

                SaveToConfigFile(model);
            }
        }

        /// <summary>
        /// 保存到配置文件
        /// </summary>
        /// <param name="model"></param>
        private void SaveToConfigFile(ManifestControllerModel model)
        {
            string xml = XmlSerializerHelper.SerializerToXml(model);
            XDocument doc = XDocument.Parse(xml);
            doc.Save(configFileFullPath);
        }

        private void btnSave_Click(object sender, EventArgs e)
        {
            ManifestControllerModel config = GetConfigModel();//检查并获取配置文件
            config.Cache = txtCacheFiles.Text.Trim();
            config.Fallback = txtFallBack.Text.Trim();
            config.Network = txtNetwork.Text.Trim();
            config.CacheDependence = txtCacheDependenceFiles.Text.Trim();
            config.SyncCacheToCacheDependence = cbSyncCacheToCacheDependence.Checked;
            config.UpdateMode = GetUpdateMode();

            SaveToConfigFile(config);

            //隐藏界面到小图标
            WindowState = FormWindowState.Minimized;
            this.ShowInTaskbar = false;
            notifyIcon1.Visible = true;
            notifyIcon1.Text = this.Text;

            listeningConfig = null;
            fileModifyTimeList = new Dictionary<string, DateTime>();
            thread = new Thread(Listening);
            thread.Start();//开始监控线程
        }

        /// <summary>
        /// 监控文件变化
        /// </summary>
        private void Listening()
        {
            while (true)
            {
                listeningConfig = GetConfigModel();//每次重新获取最新配置文件

                switch (listeningConfig.UpdateMode)
                {
                    case 0://检查Cache依赖
                        if (fileModifyTimeList.Count == 0)
                        {
                            //重新生成监控文件列表
                            string cacheDependenceList;
                            if (listeningConfig.SyncCacheToCacheDependence)
                            {
                                cacheDependenceList = listeningConfig.Cache;//使用和CACHE相同的依赖 
                            }
                            else
                            {
                                cacheDependenceList = listeningConfig.CacheDependence;//使用独立依赖
                            }

                            //生成文件列表
                            string[] dependenceFileList = cacheDependenceList.Split(new[] { "\r", "\n" }, StringSplitOptions.RemoveEmptyEntries);
                            List<string> allFiles = new List<string>();
                            foreach (var item in dependenceFileList)
                            {
                                string fullFilePath = (currentDirectory + "\\" + item.Replace("/", "\\")).Replace("\\\\", "\\"); //Path.Combine(currentDirectory, item.Replace("/","\\"));
                                if (item.EndsWith("/") && Directory.Exists(fullFilePath))
                                {
                                    //遍历文件夹
                                    var childrenFiles = Directory.GetFiles(fullFilePath, "*", SearchOption.AllDirectories);
                                    allFiles.AddRange(childrenFiles);
                                }
                                else
                                {
                                    allFiles.Add(fullFilePath);//目录不存在或是单个文件
                                }
                            }
                            //将文件加入集合
                            foreach (var file in allFiles)
                            {
                                fileModifyTimeList[file] = File.Exists(file) ? File.GetLastWriteTime(file) : DateTime.MinValue;
                            }
                        }
                        else
                        {
                            //继续监控
                            var keys = fileModifyTimeList.Keys.ToList();/*直接遍历fileModifyTimeList则不能在循环中修改集合*/
                            foreach (var item in keys)
                            {
                                DateTime updateTime = fileModifyTimeList[item];
                                if (File.Exists(item) && File.GetLastWriteTime(item) != updateTime)
                                {
                                    //文件被修改
                                    if (!listeningConfig.Updated)
                                    {
                                        listeningConfig.Updated = true;
                                        SaveToConfigFile(listeningConfig);//保存最新状态
                                    }
                                    fileModifyTimeList[item] = File.GetLastWriteTime(item);//更新最新时间
                                }
                            }
                        }
                        break;
                    case 1://始终更新
                        listeningConfig.Updated = true;
                        SaveToConfigFile(listeningConfig);
                        return;//退出
                    case 2://始终不更新
                        if (listeningConfig.Updated)
                        {
                            listeningConfig.Updated = false;
                            SaveToConfigFile(listeningConfig);
                        }
                        return;//退出
                    default:
                        break;
                }

                Thread.Sleep(TimeSpan.FromSeconds(1));//间隔1秒
            }
        }

        /// <summary>
        /// 获取配置信息
        /// </summary>
        /// <returns></returns>
        private ManifestControllerModel GetConfigModel()
        {
            XDocument configDoc = XDocument.Load(configFileFullPath);
            ManifestControllerModel configModel = XmlSerializerHelper.DeserializeToEntity<ManifestControllerModel>(configDoc.ToString());
            return configModel;
        }

        private void groupBox4_Paint(object sender, PaintEventArgs e)
        {
            e.Graphics.Clear(this.BackColor);
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            currentDirectory = Directory.GetCurrentDirectory();
            configFileFullPath = Path.Combine(currentDirectory, configFileName);
            fileModifyTimeList = new Dictionary<string, DateTime>();

            CheckConfigFile();//配置文件

            BindConfig();//绑定数据
        }


        /// <summary>
        /// 绑定数据
        /// </summary>
        private void BindConfig()
        {
            ManifestControllerModel config = GetConfigModel();

            txtCacheFiles.Text = config.Cache.Replace("\n", "\r\n");
            txtFallBack.Text = config.Fallback.Replace("\n", "\r\n");
            txtNetwork.Text = config.Network.Replace("\n", "\r\n");
            txtCacheDependenceFiles.Text = config.CacheDependence.Replace("\n", "\r\n");
            cbSyncCacheToCacheDependence.Checked = config.SyncCacheToCacheDependence;

            rbUpdateMode0.Checked = config.UpdateMode == 0;
            rbUpdateMode1.Checked = config.UpdateMode == 1;
            rbUpdateMode2.Checked = config.UpdateMode == 2;
        }

        /// <summary>
        /// 获取更新模式
        /// </summary>
        /// <returns></returns>
        private int GetUpdateMode()
        {
            foreach (var item in groupBox4.Controls)
            {
                var rbUpdateMode = item as RadioButton;
                if (rbUpdateMode != null && rbUpdateMode.Checked)
                {
                    return int.Parse(rbUpdateMode.Name.Last().ToString());
                }
            }
            return 0;
        }

        private void notifyIcon1_MouseDoubleClick(object sender, MouseEventArgs e)
        {
            this.ShowInTaskbar = true;
            notifyIcon1.Visible = false;
            if (thread != null && thread.ThreadState == ThreadState.Running)
            {
                thread.Abort();
            }
            WindowState = FormWindowState.Normal;
        }

        private void Form1_FormClosed(object sender, FormClosedEventArgs e)
        {
            System.Environment.Exit(0);//强制退出所有线程
        }
    }
}
